package com.atxiaodei.io.BIO;

import java.io.*;

/**
 * @ClassName 使用BIO进行文件拷贝
 * @Deacription TODO
 * @Author 卡布达
 * @Date 2021/10/31 13:37
 * @Version 1.0
 **/
public class 文件拷贝 {
    /**
     * 拷贝文件（方法一）无缓冲读写文件
     * @param src 被拷贝的文件
     * @param dest 拷贝到的目的地
     */
    public static void copyByFileStream(File src, File dest){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        long start = System.currentTimeMillis();
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dest);
            int b = 0;
            while((b = fis.read()) != -1){//一个字节一个字节的读
                fos.write(b);//一个字节一个字节的写
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("使用FileOutputStream拷贝大小"+getSize(src)+"的文件未使用缓冲数组耗时："+(System.currentTimeMillis()-start)+"毫秒");
    }

    /**
     * 拷贝文件（方法二）自定义数组做缓冲读写文件
     * @param src 被拷贝的文件
     * @param dest 拷贝到的目的地
     * @param size 缓冲数组大小
     */
    public static void copyByFileStream(File src,File dest,int size){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        long start = System.currentTimeMillis();
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dest);
            int b = 0;
            byte[] buff = new byte[size];//定义一个缓冲数组
            //读取一定量的数据（read返回值表示这次读了多少个数据）放入数组中
            while((b = fis.read(buff)) != -1){
                fos.write(buff,0,b);//一次将读入到数组中的有效数据（索引[0,b]范围的数据）写入输出流中
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("使用FileOutputStream拷贝大小"+getSize(src)+"的文件使用了缓冲数组耗时："+(System.currentTimeMillis()-start)+"毫秒，生成的目标文件大小为"+getSize(dest));
    }

    /**
     * 拷贝文件（方法三）使用BufferedXXX类使用默认大小缓冲来读写文件
     * @param src
     * @param dest
     */
    public static void copyByBufferedStream(File src,File dest) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        long start = System.currentTimeMillis();
        try{
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(dest));
            int b = 0;
            while( (b = bis.read())!=-1){
                bos.write(b);//使用BufferedXXX重写的write方法进行写入数据。该方法看似未缓冲实际做了缓冲处理
            }
            bos.flush();
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("使用BufferedXXXStream拷贝大小"+getSize(src)+"的文件使用了缓冲数组耗时："+(System.currentTimeMillis()-start)+"毫秒");
    }

    /**
     * 拷贝文件（方法四）使用BufferedXXX类自定义大小缓冲来读写文件
     * @param src 被拷贝的文件对象
     * @param dest 拷贝目的地文件对象
     * @param size 自定义缓冲区大小
     */
    public static void copyByBufferedStream(File src,File dest,int size) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        long start = System.currentTimeMillis();
        try{
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(dest));
            int b = 0;
            byte[] buff = new byte[size];
            while( (b = bis.read(buff))!=-1){//数据读入缓冲区
                bos.write(buff,0,b);//将缓存区数据写入输出流中
            }
            // 如果未使用flush，带来的后果可能会造成部分数据丢失
            bos.flush();
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            close(bos,bis);
        }
        System.out.println("使用BufferedXXXStream拷贝大小"+getSize(src)+"的文件使用了缓冲数组耗时："+(System.currentTimeMillis()-start)+"毫秒");
    }

    private static Long getSize(File src) {
        return  src.length();
    }

    private static void close(BufferedOutputStream bos, BufferedInputStream bis) {
        try {
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
